using System;
using System.Drawing;

using SdlDotNet.Core;
using SdlDotNet.Input;

using Game.Utils;
using Game.Data;
using Game.Input;
using Game.Input.Devices;
using Game.Output;

namespace Game
{
	public static class CGameLoop
	{	
		private const long FRAMES_PER_CYCLE = 1000;	
		
		private static float	m_timer;
		private static long		m_currentFrame; // between 0 and FRAMES_PER_CYCLE
		private static float	m_timeOfOneFrame;
		private static float	m_framesPerSecond;
		
		public static void Initialize()
		{		
			CConsole.ReportClassInit(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.Name);
			
			CTimer.Initialize(); // to log how many seconds passed
			
			m_framesPerSecond	=
				(float)Convert.ToDouble(CData.Settings.Get("FRAMES_PER_SECOND"));
			m_timeOfOneFrame	= 1.0f / m_framesPerSecond;
			m_currentFrame		= 0;
			
			// input system
			CMouseHandler.Initialize();
			CKeyboardHandler.Initialize();
			CCommands.Initialize();
			
			// graphics
			CScreen.Initialize();
			
			// force event handlers to listen to events
			Events.Quit +=
				new EventHandler<QuitEventArgs>(ApplicationQuitEventHandler);
			Events.Tick +=
				new EventHandler<TickEventArgs>(ApplicationTickEventHandler);
		}
		
		// what to happen every tick
		public static void ApplicationTickEventHandler(object sender, TickEventArgs args)
		{
			CTimer.Update();
			
			m_timer += CTimer.ElapsedTimeInSeconds;
			
			if (m_timer >= m_timeOfOneFrame)
			{				
				// execute commands every ... seconds
				if (m_currentFrame % (m_framesPerSecond * 3) == 0)
					CCommands.Execute();
				
				// handle inputs
				CKeyboardHandler.Process();
				CMouseHandler.Process();				
				
				// render screen
				CScreen.Render();	
				
				if (++m_currentFrame > FRAMES_PER_CYCLE)
					m_currentFrame = 0;
				
				m_timer = 0.0f;
			}
		}
		
		// what to happen on user sent quit request
		public static void ApplicationQuitEventHandler(object sender, QuitEventArgs args)
		{
			Events.QuitApplication();
		}
		
		# region properties
		
		public static float Timer
		{
			get { return m_timer; }
		}
		
		# endregion properties
	}
}
